


//Define the function sys_fail()
//int sys_fail(int ith, int ncall, struct syscall_failure* calls); 
//store it in arch/i386/kernel/syscall_fail.c. 
//change makefile in the dir accordingly 


//syscall_fail()

#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include<include/linux/syscall_fail.h>


asmlinkage long syscall_fail(long syscall_nr) {

		int n;
		int i=-1;
		long ret;
		
		for(n=0;n<current->updater->ncall;n++)
		{
				if(current->updater->calls[n].syscall_nr==sycall_nr)//something from task_struct)
				{
						current->updater->counter++;
						if(current->updater->counter==current->updater->ith)
						{
								//XXXXXXX-------call fail() or call syscall_fail() accordingly--  or return calls[n].error
								//free up memory
                              ret= current->updater->calls[n].error;
						free_fail();
						return ret;
						}
						else
						{
							return 0;
								//let the system call execute
						}


				}
		}





		/*...
		...
		Logic for determining if error code needs to be returned
		...
		If an error code needs to be returned, 
                     free up memory used for failure injection
                     and return error code.*/
	} 
        


int sys_fail(int ith, int ncall, struct syscall_failure* calls)

{
		//xxxxxx---memory allocation  ---- initialization -- kalloc()

if(ith<0)
	{
	return -1;
	}
int m=-1;
//2 more error codes to take care
//extra fail call to end as well
  current->updater=kmalloc(sizeof(struct syscall_fail_updater),GFP_KERNEL);
  current->updater->calls=kmalloc((ncall*sizeof(struct syscall_failure)),GFP_KERNEL);

	copy_from_user(&(current->updater->counter),&m,sizeof(m));
	copy_from_user(&(current->updater->ith),&ith,sizeof(ith));//figure out

    copy_from_user(&(current->updater->ncall),&ncall,sizeof(ncall));

    copy_from_user(current->updater->calls,calls,(ncall*sizeof(struct syscall_failure)));

		//current->updater->ith=
		//current->updater->ncall=
		//current->updater->calls=
		return 1;



}



//to prevent memory leak
//defining a function free_fail()

void free_fail()
{
	kfree(current->updater->calls);
	kfree(current->updater);
}

//This function should free memory you use for failure injection.
//You should call this function from free_task  in kernel/fork.c


